package com.ecoolex.ying.space.core.manager;

import java.time.Instant;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.common.util.StringUtil;
import com.ecoolex.ying.space.core.dao.UserFavoriteDAO;
import com.ecoolex.ying.space.entity.UserFavorite;
import com.ecoolex.ying.space.entity.UserFavorite.Column;
import com.ecoolex.ying.space.entity.UserFavoriteExample;
import com.ecoolex.ying.space.pojo.AddUserFavoriteDTO;


@Service
public class UserFavoriteManager {

    @Autowired
    private UserFavoriteDAO dao;

    @Autowired
    private UserFavoriteItemsManager userFavoriteItemsManager;

    public UserFavorite getByIdAndUserId(Integer userId, Integer favoriteId) {
        UserFavoriteExample example = new UserFavoriteExample();
        example.createCriteria().andFavoriteIdEqualTo(favoriteId).andUserIdEqualTo(userId).andDeletedEqualTo(
            UserFavorite.NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    public Pagination<UserFavorite> queryUserFavoriteList(Integer userId, Sorting[] sorts, Page page) {
        UserFavoriteExample example = new UserFavoriteExample();
        UserFavoriteExample.Criteria criteria = example.createCriteria();
        criteria.andLogicalDeleted(UserFavorite.NOT_DELETED);
        criteria.andUserIdEqualTo(userId);

        example.orderBy(Sortings.builder(sorts).verify(UserFavorite.Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());
        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    private long countFavoriteNumberByUserId(Integer userId) {
        UserFavoriteExample example = new UserFavoriteExample();
        example.createCriteria().andUserIdEqualTo(userId).andDeletedEqualTo(UserFavorite.NOT_DELETED);
        return dao.countByExample(example);
    }

    private UserFavorite getByNameAndUserId(Integer userId, String favoriteName, Integer notContainFavoriteId) {
        UserFavoriteExample example = new UserFavoriteExample();
        UserFavoriteExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId).andNameEqualTo(favoriteName).andDeletedEqualTo(UserFavorite.NOT_DELETED);
        if (Check.notNull(notContainFavoriteId)) {
            criteria.andFavoriteIdNotEqualTo(notContainFavoriteId);
        }
        return dao.selectOneByExample(example);
    }

    private void verify(UserFavorite record) {
        BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "收藏夹名称为空");
        BizAssert.isTrue(Check.notNull(record.getPublicity()), ResultCode.VERIFY.build(11), "收藏夹是否公开为空");

        String newName = StringUtil.trim(record.getName());
        // 字符长度为20个
        BizAssert.isTrue(StringUtil.gbkLength(newName) <= 20, ResultCode.VERIFY.build(12), "收藏夹名称最大支持20个字符");
        // 不能重名
        UserFavorite byName = getByNameAndUserId(record.getUserId(), newName, record.getFavoriteId());
        BizAssert.isTrue(Check.isNull(byName), ResultCode.VERIFY.build(13), "收藏夹名称已经存在");
        // 限制10个收藏夹
        long number = countFavoriteNumberByUserId(record.getUserId());
        BizAssert.isTrue(number < 10, ResultCode.VERIFY.build(14), "收藏夹最大支持10个");
        // 处理过的name
        record.setName(newName);
    }

    public UserFavorite add(Integer userId, AddUserFavoriteDTO add, String createUser) {
        UserFavorite record = new UserFavorite();
        record.setUserId(userId);
        record.setName(add.getName());
        record.setPublicity(add.getPublicity());
        record.setIsDefault(false);
        record.setDeleted(UserFavorite.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));

        verify(record);

        dao.insert(record);
        return record;
    }

    public void addDefault(Integer userId, String createUser) {
        UserFavorite record = new UserFavorite();
        record.setUserId(userId);
        record.setIsDefault(true);
        record.setName("默认收藏夹");
        record.setPublicity(true);
        record.setDeleted(UserFavorite.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);
    }

    public UserFavorite edit(UserFavorite record, String updateUser) {
        record.setDeleted(UserFavorite.NOT_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        verify(record);
        BizAssert.isTrue(!record.getIsDefault(), ResultCode.VERIFY.build(20), "默认收藏夹无法编辑");

        dao.updateByPrimaryKeySelective(record, Column.name, Column.publicity, Column.updateUser, Column.updateTime);
        return record;
    }

    public void delete(UserFavorite record, String updateUser) {
        // 默认的不能删除
        BizAssert.isTrue(!record.getIsDefault(), ResultCode.BIZ.build(2), "默认收藏夹无法删除");
        // 有内容的无法删除
        long childCount = userFavoriteItemsManager.countByFavoriteId(record.getFavoriteId());
        BizAssert.isTrue(childCount < 1, ResultCode.BIZ.build(1), "存在{}个收藏内容,无法删除", childCount);

        record.setDeleted(UserFavorite.IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record,
            UserFavorite.Column.deleted,
            UserFavorite.Column.updateUser,
            UserFavorite.Column.updateTime);
    }

    public void setPublic(UserFavorite record, String updateUser) {
        record.setPublicity(true);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record,
            UserFavorite.Column.publicity,
            UserFavorite.Column.updateUser,
            UserFavorite.Column.updateTime);
    }

    public void cancelPublic(UserFavorite record, String updateUser) {
        record.setPublicity(false);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record,
            UserFavorite.Column.publicity,
            UserFavorite.Column.updateUser,
            UserFavorite.Column.updateTime);
    }
}